#!/bin/python
# -*- coding: utf-8 -*-
"""
Name: sdk_packer.py
Author: harrybao
Mail: harrybao@123u.com
Time: 2021/07/12 16:53
Desc: 打包生成SDK交付包
"""

import os
import tarfile
import platform
import shutil
import json
import time
from path_util import PathUtil
from global_var import *

def json_has_attr(json_config, attr, print_error=True):
    if attr in json_config and json_config[attr] is not None:
        if print_error:
            print('json attr not exist: {0}'.format(attr))
        return True
    return False

class SDKPacker:
    """SDK打包"""
    def __init__(self, output_path, project_name, package_name, package_lang, package_version):
        """初始化
            - output_path: SDK交付包生成路径
            - project_name: 工程名字
            - package_name: SDK交付包名字
            - package_lang: SDK使用语言
            - package_version: SDK版本
        """
        self._output_path = output_path
        self._package_name = package_name
        self._package_lang = package_lang
        self._project_name = project_name
        self._package_version = package_version

    def tarfile_name(self):
        """获取压缩包名字
            生成名字格式例如：guildservice-sdk-cpp-windows-0.1.0-all.tar.gz
        """
        return os.path.join(
            self._output_path, '{0}-sdk-{1}-{2}-{3}-all.tar.gz'.format(
                self._package_name, self._package_lang, platform.system().lower(), self._package_version))

    def make_targz(self, source_dir_list):
        """压缩成tar.gz文件
        """
        output_filename = self.tarfile_name()
        with tarfile.open(output_filename, "w:gz") as tar:
            for source_dir in source_dir_list:
                print('-- packing: {0}'.format(source_dir))
                tar.add(source_dir, arcname=os.path.basename(source_dir))

    
    def pack(self, idl_list):
        """打包
            - idl_list: idl名字列表
        """
        path_util = PathUtil()

        package_path = os.path.join(path_util.guild_service_root_path, 'package')
        package_include_path = os.path.join(package_path, 'include')
        package_lib_path = os.path.join(package_path, 'lib')
        package_protobuf_path = os.path.join(package_path, 'protobuf')
        package_proxy_path = os.path.join(package_path, 'proxy')
        package_stub_path = os.path.join(package_path, 'stub')
        package_info_path = os.path.join(package_path, 'info')
        package_doc_path = os.path.join(package_path, 'doc')

        dst_path_list = []

        json_data = {}
        json_data['version'] = '0.1.0'
        json_data['author'] = {'name': 'harrybao', 'mail': 'harrybao@123u.com'}
        json_data['package'] = 'guildservice-sdk-cpp-windows-0.1.0-all.tar.gz'
        json_data['displayName'] = '中台公会服务交付包'
        json_data['idl'] = {}
        json_data['date'] = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())


        #########################################################################
        # include/struct
        src_path = os.path.join(
            path_util.service_box_root_path, 'src/repo/src/include')
        dst_path = os.path.join(package_include_path,
                               'struct/{0}'.format(self._project_name))
        os.makedirs(dst_path, 0o777, True)
        for idl_name in idl_list:
            src_idl_path = os.path.join(src_path, idl_name)
            dst_idl_path = os.path.join(dst_path, idl_name)
            if not path_util.check_path(src_idl_path, False):
                continue
            
            json_data['idl'][idl_name] = {}
            json_idl_dic = json_data['idl'][idl_name]
            json_idl_dic['desc'] = idl_name
            json_idl_dic['struct'] = []
            json_idl_dic['service'] = {}

            os.makedirs(dst_idl_path, 0o777, True)
            for file_name in os.listdir(src_idl_path):
                if file_name.endswith('struct.h') or file_name.endswith('enum.h'):
                    shutil.copy2(os.path.join(
                        src_path, idl_name, file_name), dst_idl_path)
                    json_idl_dic['struct'].append(file_name)

        dst_path_list.append(dst_path)

        #########################################################################
        # include/proxy
        src_path = os.path.join(
            path_util.service_box_root_path, 'src/repo/src/include')
        dst_path = os.path.join(package_include_path,
                               'proxy/{0}'.format(self._project_name))
        os.makedirs(dst_path, 0o777, True)
        for idl_name in idl_list:
            if not json_has_attr(json_data['idl'], idl_name):
                continue
            json_idl_dic = json_data['idl'][idl_name]

            for service_name in g_service_dic[idl_name]:
                json_idl_dic['service'][service_name] = {}
                json_service_dic = json_idl_dic['service'][service_name]
                json_service_dic['include'] = {}
                json_service_dic['include']['proxy'] = []

                src_idl_service_path = os.path.join(src_path, idl_name, service_name, 'proxy')
                if not path_util.check_path(src_idl_service_path):
                    continue
                dst_idl_service_path = os.path.join(dst_path, idl_name, service_name)
                os.makedirs(dst_idl_service_path, 0o777, True)
                for file_name in os.listdir(src_idl_service_path):
                    if file_name.endswith('proxy.h'):
                        shutil.copy2(os.path.join(src_idl_service_path, file_name), dst_idl_service_path)
                        json_service_dic['include']['proxy'].append(file_name)

        dst_path_list.append(dst_path)

        #########################################################################
        # protobuf
        src_path = os.path.join(
            path_util.service_box_root_path, 'src/repo/lib')
        dst_path = os.path.join(package_protobuf_path, self._project_name)
        os.makedirs(dst_path, 0o777, True)
        for idl_name in idl_list:
            if not json_has_attr(json_data['idl'], idl_name):
                continue
            json_idl_dic = json_data['idl'][idl_name]
            json_idl_dic['service']['protobuf'] = []

            path = os.path.join(src_path, idl_name)
            if platform.system() == 'Windows':
                path = os.path.join(path, 'Release')
            if not path_util.check_path(path):
                continue
            for file_name in os.listdir(path):
                if file_name.endswith('.a'):
                    shutil.copy2(os.path.join(path, file_name), dst_path)
                    json_idl_dic['service']['protobuf'].append(file_name)

        dst_path_list.append(dst_path)

        #########################################################################
        # proxy   
        src_path = os.path.join(
            path_util.service_box_root_path, 'src/repo/lib/proxy')
        dst_path = os.path.join(package_proxy_path, self._project_name)
        os.makedirs(dst_path, 0o777, True)
        for idl_name in idl_list:
            if not json_has_attr(json_data['idl'], idl_name):
                continue

            json_idl_dic = json_data['idl'][idl_name]

            for service_name in g_service_dic[idl_name]:
                json_idl_dic['service'][service_name]['proxyLib'] = []

                path = os.path.join(src_path, idl_name, service_name)
                if platform.system() == 'Windows':
                    path = os.path.join(path, 'Release')
                if not path_util.check_path(path):
                    continue
                for file_name in os.listdir(path):
                    if file_name.endswith('.a'):
                        shutil.copy2(os.path.join(path, file_name), dst_path)
                        json_idl_dic['service'][service_name]['proxyLib'].append(file_name)

        dst_path_list.append(dst_path)
        #########################################################################
        # stub
        src_path = os.path.join(
            path_util.service_box_root_path, 'src/repo/lib/stub')
        dst_path = os.path.join(package_stub_path, self._project_name)
        os.makedirs(dst_path, 0o777, True)
        for idl_name in idl_list:
            if not json_has_attr(json_data['idl'], idl_name):
                continue

            json_idl_dic = json_data['idl'][idl_name]

            for service_name in g_service_dic[idl_name]:
                json_idl_dic['service'][service_name]['stubLib'] = []

                path = os.path.join(src_path, idl_name, service_name)
                if platform.system() == 'Windows':
                    path = os.path.join(path, 'Release')
                if not path_util.check_path(path):
                    continue
                for file_name in os.listdir(path):
                    if file_name.endswith('.a'):
                        shutil.copy2(os.path.join(path, file_name), dst_path)
                        json_idl_dic['service'][service_name]['stubLib'].append(file_name)

        dst_path_list.append(dst_path)

        #########################################################################
        # serviceLib
        src_path = os.path.join(
            path_util.service_box_root_path, 'src/repo/lib/stub')
        dst_path = os.path.join(package_lib_path, self._project_name)
        os.makedirs(dst_path, 0o777, True)
        for idl_name in idl_list:
            if not json_has_attr(json_data['idl'], idl_name):
                continue

            json_idl_dic = json_data['idl'][idl_name]

            for service_name in g_service_dic[idl_name]:
                json_idl_dic['service'][service_name]['serviceLib'] = []

                path = os.path.join(src_path, idl_name, service_name)
                if platform.system() == 'Windows':
                    path = os.path.join(path, 'Release')
                if not path_util.check_path(path):
                    continue
                for file_name in os.listdir(path):
                    if file_name.endswith('.so'):
                        shutil.copy2(os.path.join(path, file_name), dst_path)
                        json_idl_dic['service'][service_name]['serviceLib'].append(file_name)

        dst_path_list.append(dst_path)
        #########################################################################
        # doc
        src_path = os.path.join(
            path_util.guild_service_root_path, 'doc')
        dst_path = os.path.join(package_doc_path, self._project_name)
        if os.path.exists(dst_path):
            shutil.rmtree(dst_path)
        # os.makedirs(dst_path, 0o777, True)
        if platform.system() == 'Windows':
            shutil.copytree(src_path, dst_path, dirs_exist_ok=True)
        else:
            shutil.copytree(src_path, dst_path)
            pass

        dst_path_list.append(dst_path)
        #########################################################################

        # output json
        dst_path = os.path.join(package_info_path, self._project_name)
        os.makedirs(dst_path, 0o777, True)

        dst_path_list.append(dst_path)

        with open(os.path.join(dst_path, 'package.json'), "w", encoding='utf-8') as f:
            json.dump(json_data, f, sort_keys=True, indent=4, ensure_ascii=False)

        self.make_targz([package_include_path, package_lib_path,
                          package_protobuf_path, package_proxy_path, package_stub_path, package_info_path, package_doc_path])

        os.system('echo {0}'.format(self.tarfile_name()))

        for path in dst_path_list:
            shutil.rmtree(path)

        pass
